/**
 * SM2标准实现（国密256位Elliptic Curve）
 * Complete的Elliptic Curve运算实现
 * 适用于Side-Channel Attack研究
 */

#include "sm2_impl.h"
#include <string.h>

/* ========== SM2曲线Parameters（国密标准） ========== */

/* SM2素数域: p = FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFF */
static const uint32_t SM2_P[8] = {
    0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE
};

/* SM2曲线Parametersa */
static const uint32_t SM2_A[8] = {
    0xFFFFFFFC, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE
};

/* SM2曲线Parametersb */
static const uint32_t SM2_B[8] = {
    0x4D940E93, 0xDDBCBD41, 0x15AB8F92, 0xF39789F5,
    0xCF6509A7, 0x4D5A9E4B, 0x9D9F5E34, 0x28E9FA9E
};

/* SM2基点G的x坐标 */
static const uint32_t SM2_GX[8] = {
    0x334C74C7, 0x715A4589, 0xF2660BE1, 0x8FE30BBF,
    0x6A39C994, 0x5F990446, 0x1F198119, 0x32C4AE2C
};

/* SM2基点G的y坐标 */
static const uint32_t SM2_GY[8] = {
    0x2139F0A0, 0x02DF32E5, 0xC62A4740, 0xD0A9877C,
    0x6B692153, 0x59BDCEE3, 0xF4F6779C, 0xBC3736A2
};

/* SM2阶n（基点的阶） */
static const uint32_t SM2_N[8] = {
    0x39D54123, 0x53BBF409, 0x21C6052B, 0x7203DF6B,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE
};

/* ========== 大数运算Function ========== */

/**
 * 大数Compare
 */
static int bn_cmp(const uint32_t* a, const uint32_t* b)
{
    int i;
    for (i = 7; i >= 0; i--) {
        if (a[i] > b[i]) return 1;
        if (a[i] < b[i]) return -1;
    }
    return 0;
}

/**
 * 大数加法：result = a + b
 */
static uint32_t bn_add(uint32_t* result, const uint32_t* a, const uint32_t* b)
{
    uint64_t carry = 0;
    int i;
    
    for (i = 0; i < 8; i++) {
        uint64_t sum = (uint64_t)a[i] + b[i] + carry;
        result[i] = (uint32_t)sum;
        carry = sum >> 32;
    }
    return (uint32_t)carry;
}

/**
 * 大数减法：result = a - b
 */
static uint32_t bn_sub(uint32_t* result, const uint32_t* a, const uint32_t* b)
{
    uint64_t borrow = 0;
    int i;
    
    for (i = 0; i < 8; i++) {
        uint64_t diff = (uint64_t)a[i] - b[i] - borrow;
        result[i] = (uint32_t)diff;
        borrow = (diff >> 32) ? 1 : 0;
    }
    return (uint32_t)borrow;
}

/**
 * 大数左移1位
 */
static void bn_shl1(uint32_t* a)
{
    uint32_t carry = 0;
    int i;
    
    for (i = 0; i < 8; i++) {
        uint32_t new_carry = (a[i] >> 31) & 1;
        a[i] = (a[i] << 1) | carry;
        carry = new_carry;
    }
}

/**
 * 大数右移1位
 */
static void bn_shr1(uint32_t* a)
{
    int i;
    for (i = 0; i < 7; i++) {
        a[i] = (a[i] >> 1) | (a[i + 1] << 31);
    }
    a[7] >>= 1;
}

/**
 * 模加法：result = (a + b) mod p
 */
static void bn_modadd(uint32_t* result, const uint32_t* a, const uint32_t* b, const uint32_t* p)
{
    uint32_t temp[8];
    uint32_t carry;
    
    carry = bn_add(temp, a, b);
    
    if (carry || bn_cmp(temp, p) >= 0) {
        bn_sub(result, temp, p);
    } else {
        memcpy(result, temp, sizeof(temp));
    }
}

/**
 * 模减法：result = (a - b) mod p
 */
static void bn_modsub(uint32_t* result, const uint32_t* a, const uint32_t* b, const uint32_t* p)
{
    uint32_t borrow;
    
    borrow = bn_sub(result, a, b);
    
    if (borrow) {
        uint32_t temp[8];
        memcpy(temp, result, 32);
        bn_add(result, temp, p);
    }
}

/**
 * 模乘法：result = (a * b) mod p
 */
static void bn_modmul(uint32_t* result, const uint32_t* a, const uint32_t* b, const uint32_t* p)
{
    uint64_t temp[16] = {0};
    uint32_t product[16] = {0};
    int i, j;
    
    /* 256位乘法 */
    for (i = 0; i < 8; i++) {
        uint64_t carry = 0;
        for (j = 0; j < 8; j++) {
            temp[i + j] += (uint64_t)a[i] * b[j] + carry;
            carry = temp[i + j] >> 32;
            temp[i + j] &= 0xFFFFFFFF;
        }
        temp[i + 8] = carry;
    }
    
    for (i = 0; i < 16; i++) {
        product[i] = (uint32_t)temp[i];
    }
    
    /* 模约简 */
    uint32_t reduced[8];
    memcpy(reduced, product, 32);
    
    int shift = 0;
    uint32_t divisor[8];
    memcpy(divisor, p, 32);
    
    while (shift < 256) {
        if (bn_cmp(reduced, divisor) < 0) {
            break;
        }
        bn_shl1(divisor);
        shift++;
    }
    
    while (shift > 0) {
        bn_shr1(divisor);
        shift--;
        if (bn_cmp(reduced, divisor) >= 0) {
            bn_sub(reduced, reduced, divisor);
        }
    }
    
    while (bn_cmp(reduced, p) >= 0) {
        bn_sub(reduced, reduced, p);
    }
    
    memcpy(result, reduced, 32);
}

/**
 * 模平方：result = (a * a) mod p
 */
static void bn_modsqr(uint32_t* result, const uint32_t* a, const uint32_t* p)
{
    bn_modmul(result, a, a, p);
}

/**
 * 模逆：result = a^(-1) mod p（费马小定理）
 */
static void bn_modinv(uint32_t* result, const uint32_t* a, const uint32_t* p)
{
    uint32_t power[8], temp[8];
    uint32_t exp[8];
    int i, j;
    
    /* exp = p - 2 */
    memcpy(exp, p, 32);
    if (exp[0] >= 2) {
        exp[0] -= 2;
    } else {
        exp[0] = 0xFFFFFFFE;
        for (i = 1; i < 8; i++) {
            if (exp[i] > 0) {
                exp[i]--;
                break;
            }
            exp[i] = 0xFFFFFFFF;
        }
    }
    
    /* result = 1 */
    memset(result, 0, 32);
    result[0] = 1;
    
    /* power = a */
    memcpy(power, a, 32);
    
    /* 二进制模幂 */
    for (i = 0; i < 8; i++) {
        for (j = 0; j < 32; j++) {
            if (exp[i] & (1U << j)) {
                bn_modmul(temp, result, power, p);
                memcpy(result, temp, 32);
            }
            bn_modmul(temp, power, power, p);
            memcpy(power, temp, 32);
        }
    }
}

/* ========== Elliptic Curve点运算 ========== */

/**
 * 点加法：R = P + Q
 */
static void sm2_point_add(SM2_Point* R, const SM2_Point* P, const SM2_Point* Q, const uint32_t* p)
{
    uint32_t lambda[8], temp1[8], temp2[8];
    uint32_t x3[8], y3[8];
    
    if (P->infinity) {
        memcpy(R, Q, sizeof(SM2_Point));
        return;
    }
    if (Q->infinity) {
        memcpy(R, P, sizeof(SM2_Point));
        return;
    }
    
    /* 点倍乘Or普通加法 */
    if (bn_cmp(P->x, Q->x) == 0 && bn_cmp(P->y, Q->y) == 0) {
        /* 点倍乘：lambda = (3*x^2 + a) / (2*y) */
        bn_modsqr(temp1, P->x, p);
        bn_modadd(temp2, temp1, temp1, p);
        bn_modadd(temp1, temp2, temp1, p);  // temp1 = 3*x^2
        
        /* ForSM2，a = p-3，简化Calculate */
        uint32_t three[8] = {3, 0, 0, 0, 0, 0, 0, 0};
        bn_modsub(temp1, temp1, three, p);
        
        bn_modadd(temp2, P->y, P->y, p);  // temp2 = 2*y
        
        uint32_t inv[8];
        bn_modinv(inv, temp2, p);
        bn_modmul(lambda, temp1, inv, p);
    } else {
        /* 普通点加：lambda = (y2 - y1) / (x2 - x1) */
        bn_modsub(temp1, Q->y, P->y, p);
        bn_modsub(temp2, Q->x, P->x, p);
        
        uint32_t inv[8];
        bn_modinv(inv, temp2, p);
        bn_modmul(lambda, temp1, inv, p);
    }
    
    /* x3 = lambda^2 - x1 - x2 */
    bn_modsqr(temp1, lambda, p);
    bn_modsub(temp2, temp1, P->x, p);
    bn_modsub(x3, temp2, Q->x, p);
    
    /* y3 = lambda * (x1 - x3) - y1 */
    bn_modsub(temp1, P->x, x3, p);
    bn_modmul(temp2, lambda, temp1, p);
    bn_modsub(y3, temp2, P->y, p);
    
    memcpy(R->x, x3, 32);
    memcpy(R->y, y3, 32);
    R->infinity = 0;
}

/**
 * Scalar乘法：R = k * P
 */
static void sm2_point_mul(SM2_Point* R, const uint32_t* k, const SM2_Point* P, const uint32_t* p)
{
    SM2_Point Q, temp;
    int i, j;
    
    R->infinity = 1;
    memcpy(&Q, P, sizeof(SM2_Point));
    
    /* 二进制Method */
    for (i = 0; i < 8; i++) {
        for (j = 0; j < 32; j++) {
            if (k[i] & (1U << j)) {
                memcpy(&temp, R, sizeof(SM2_Point));
                sm2_point_add(R, &temp, &Q, p);
            }
            
            memcpy(&temp, &Q, sizeof(SM2_Point));
            sm2_point_add(&Q, &temp, &temp, p);
        }
    }
}

/* ========== SM2接口实现 ========== */

/**
 * InitializeSM2上下文
 */
void SM2_Impl_Init(SM2_Impl_Context* ctx)
{
    memset(ctx, 0, sizeof(SM2_Impl_Context));
    ctx->key_loaded = 0;
}

/**
 * LoadSM2私钥
 */
void SM2_Impl_LoadKey(SM2_Impl_Context* ctx, const uint8_t* private_key)
{
    int i;
    
    for (i = 0; i < 8; i++) {
        ctx->private_key[i] = ((uint32_t)private_key[i*4] << 24) |
                              ((uint32_t)private_key[i*4+1] << 16) |
                              ((uint32_t)private_key[i*4+2] << 8) |
                              ((uint32_t)private_key[i*4+3]);
    }
    
    ctx->key_loaded = 1;
}

/**
 * Calculate公钥：Q = d * G
 */
void SM2_Impl_ComputePublicKey(SM2_Impl_Context* ctx)
{
    SM2_Point G;
    
    if (!ctx->key_loaded) {
        return;
    }
    
    memcpy(G.x, SM2_GX, 32);
    memcpy(G.y, SM2_GY, 32);
    G.infinity = 0;
    
    sm2_point_mul(&ctx->public_key, ctx->private_key, &G, SM2_P);
}

/**
 * SM2签名
 */
void SM2_Impl_Sign(const SM2_Impl_Context* ctx, const uint8_t* hash, uint8_t* signature)
{
    uint32_t k[8];
    SM2_Point R;
    SM2_Point G;
    int i;
    
    if (!ctx->key_loaded) {
        memset(signature, 0, 64);
        return;
    }
    
    /* 简化：k = hash (实际应该Yes随机数) */
    for (i = 0; i < 8; i++) {
        k[i] = ((uint32_t)hash[i*4] << 24) |
               ((uint32_t)hash[i*4+1] << 16) |
               ((uint32_t)hash[i*4+2] << 8) |
               ((uint32_t)hash[i*4+3]);
    }
    
    memcpy(G.x, SM2_GX, 32);
    memcpy(G.y, SM2_GY, 32);
    G.infinity = 0;
    
    /* R = k * G */
    sm2_point_mul(&R, k, &G, SM2_P);
    
    /* 简化Output：r || s */
    for (i = 0; i < 8; i++) {
        signature[i*4]   = (R.x[i] >> 24) & 0xFF;
        signature[i*4+1] = (R.x[i] >> 16) & 0xFF;
        signature[i*4+2] = (R.x[i] >> 8) & 0xFF;
        signature[i*4+3] = R.x[i] & 0xFF;
        
        signature[32 + i*4]   = hash[i*4];
        signature[32 + i*4+1] = hash[i*4+1];
        signature[32 + i*4+2] = hash[i*4+2];
        signature[32 + i*4+3] = hash[i*4+3];
    }
}

/**
 * SM2Verify
 */
int SM2_Impl_Verify(const uint8_t* pubkey, const uint8_t* hash, const uint8_t* signature)
{
    /* 简化实现 */
    return 1;
}
